#pragma once

#include "IStickyTweetsApp.h"
#include "InternetContext.h"

class StickyTweetsAppXP : public IStickyTweetsApp
{
public:
  static StickyTweetsAppXP& GetInstance(VOID);

public:
  StickyTweetsAppXP(VOID);
  ~StickyTweetsAppXP(VOID);

private:
  StickyTweetsAppXP(StickyTweetsAppXP&) {};

public:
  CString GetVersion(VOID);

  StickyTweetsStatus LoadSettings(bool reload = false);
  StickyTweetsStatus SaveSettings(const Settings& settings);
  Settings GetSettings(VOID);

  /*!
   * \brief   Open the main Internet async context and set a callback
   */
  StickyTweetsStatus OpenMainContext(INTERNET_STATUS_CALLBACK context);

  void GetScreenNames(CAtlList<CString>& list);

  /*!
   * \brief   Save the screen name last used to log in
   */
  StickyTweetsStatus SetLastScreenName(const CString& screenName);

  /*!
   * \brief   Even though the SearchFilters is a Settings property we want some convenience methods
   */
  VOID GetSearchFilterList(CAtlList<CString>& list);
  StickyTweetsStatus UpdateSearchFilter(const CString& searchTerm, BOOL add);
  BOOL IsSearchFilter(const CString& searchTerm);

  StickyTweetsStatus SetSystemError(LONG errorCode);
  CString GetSystemError(VOID);

  StickyTweetsStatus SetTwitterError(const CString& errorXml);
  CString GetTwitterError(VOID);

  StickyTweetsStatus VerifyCredentials(const TCHAR* screenName, const TCHAR* password);

  StickyTweetsStatus GetCurrentTimelineXml(CString& xml, CString sinceId = L"");
  StickyTweetsStatus GetMentions(CString& xml, CString sinceId = L"");
  StickyTweetsStatus GetDirectXml(CString& xml, CString sinceId = L"");
  StickyTweetsStatus GetSentDirectXml(CString& xml, CString sinceId = L"");
  StickyTweetsStatus GetUserTimelineXml(const CString& screenName, CString& xml);
  StickyTweetsStatus GetSearchAtom(const CString& query, CString& atomXml);

  /*!
   * \brief   Get the request object for a given request handle
   * \returns Pointer to object or NULL on error/missing
   */
  RequestContext* GetRequestContext(HINTERNET hInternet);

  /*!
   * \brief   Delete a request object
   */
  StickyTweetsStatus DeleteRequestContext(HINTERNET hInternet);

  /*!
   * \brief   Returns TRUE if a request of the give type is currently active
   */
  BOOL IsRequested(RequestType type);

  StickyTweetsStatus ResetMainContext(VOID);

  BOOL IsFollowing(const CString& screenName);

  StickyTweetsStatus DownloadImage(const CString& imageUrl, Image** image);

  StickyTweetsStatus UpdateStatus(const CString& status, const CString& inReplyToId);
  StickyTweetsStatus SendDm(const CString& user, const CString& text);

  StickyTweetsStatus Follow(const CString& screenName, BOOL follow);

  StickyTweetsStatus TrimUrl(const CString& original, CString& trimmed);
  BOOL IsTrimmed(const CString& url);

  /*!
   * \brief   Roll my own because the only thing I found in Win32 was in the Indexing Service & I don't want to link another lib
   */
  CString EncodeUri(const CString& uri);

  /*!
   * \brief   Parse a date string into a CTime
   */
  CTime ParseDate(const CString& date);

  CString FormatDate(const CString& date);

  /*!
   * \brief   Retrieve the local cache filename for a URL
   *
   * Downloads the file if no cache entry exists.
   */
  StickyTweetsStatus DownloadImageToCache(const CString& imageUrl, CString& localFilename);

  /*!
   * \brief   Extract the status code from a response
   */
  StickyTweetsStatus GetStatusCode(HINTERNET hRequest, LPDWORD statusCode);
  
  /*!
   * \brief   Retrieve status elements XML from Twitter
   */
  StickyTweetsStatus GetTwitterXml(const TCHAR* objectName, CString& xmlResponse);
  StickyTweetsStatus GetTwitterXml(const TCHAR* server, const TCHAR* objectName, CString& xmlResponse);
  StickyTweetsStatus GetWebServiceXml(const TCHAR* server, const TCHAR* objectName, const TCHAR* userName, const TCHAR* password, CString& xmlResponse);
  StickyTweetsStatus GetWebResponse(const TCHAR* server, const TCHAR* objectName, const TCHAR* userName, const TCHAR* password, CString& response, BOOL requireXml, const TCHAR* verb = L"GET");

  /*!
   * \brief   Read a response from an Internet connection
   * \param   requireXml - If TRUE, this will return an error if response is not XML
   */
  StickyTweetsStatus ReadResponse(HINTERNET hRequest, CString& response, BOOL requireXml);

private:
  CString _rs;

  Settings _settings; //< Stored user settings
  BOOL _settingsLoaded; //< set to true when settings have been loaded at least once

  CString _systemError;
  CString _twitterError;

  MainContext _mainContext;
  MainContext _searchContext;
  CAtlList<RequestContext*> _requestContexts;
};
